﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using YArchitech.ProgressBar;
using HYOpeningCommon.DbOpening;
using HYOpeningCommon.OpeningProfile;
using HYOpeningCommon.Public;
using HYOpeningDesignInput.Public;

namespace HYOpeningDesignInput.DbOpeningCreatorFactory
{
	internal class DbBeamOpeningCreatorFactory : DbOpeningBaseCreatorFactory
	{
		public DbBeamOpeningCreatorFactory(ref List<Document> lstDoc, WindowHandle handle, Dictionary<string, int> dicOpeningProfileData) : base(ref lstDoc, handle, dicOpeningProfileData)
		{
		}

		public override bool CreateDbOpening(MEPData mepData, ref LinkedList<DbOpeningBase> lstDbOpening)
		{
			return this.GetOpeningDataByDuct(mepData.m_lstDuct, mepData.m_lstInfos, ref lstDbOpening) && this.GetOpeningDataByCableTray(mepData.m_lstCableTray, mepData.m_lstInfos, ref lstDbOpening) && this.GetOpeningDataByPipe(mepData.m_lstPipe, mepData.m_lstInfos, ref lstDbOpening);
		}

		private bool GetOpeningDataByDuct(List<Duct> lstDuct, List<HYOpeningDesignInput.Public.PointSort> lstInfos, ref LinkedList<DbOpeningBase> lstDbOpening)
		{
			ProgressBarForm progressBarForm = new ProgressBarForm(lstDuct.Count, ProgressBarStyle.Blocks, true);
			try
			{
				progressBarForm.Text = "风管和梁碰撞检测";
				progressBarForm.ShowInTaskbar = false;
				progressBarForm.Show(this.m_hWndRevit);
				List<FamilyInstance> list = new List<FamilyInstance>();
				foreach (Duct duct in lstDuct)
				{
					foreach (Autodesk.Revit.DB.Document doc in this.m_lstDoc)
					{
						list.AddRange(Interface.GetAllIntersectSubject<FamilyInstance>(duct, doc, BuiltInCategory.OST_StructuralFraming));
					}
					if (list.Count == 0)
					{
						progressBarForm.RefreshProgressBar();
					}
					else
					{
						if (!this.TraveAllBeam(list, duct, lstInfos, ref lstDbOpening))
						{
							progressBarForm.Dispose();
							return false;
						}
						list.Clear();
						progressBarForm.RefreshProgressBar();
						if (progressBarForm.m_stopTag)
						{
							return false;
						}
					}
				}
				progressBarForm.Dispose();
			}
			catch (Exception ex)
			{
				progressBarForm.Dispose();
				ExceptionLog.WriteLog(ex.Message, true);
				return false;
			}
			return true;
		}

		private bool GetOpeningDataByCableTray(List<CableTray> lstCableTary, List<HYOpeningDesignInput.Public.PointSort> lstInfos, ref LinkedList<DbOpeningBase> lstDbOpening)
		{
			ProgressBarForm progressBarForm = new ProgressBarForm(lstCableTary.Count, ProgressBarStyle.Blocks, true);
			try
			{
				progressBarForm.Text = "电缆桥架和梁碰撞检测";
				progressBarForm.ShowInTaskbar = false;
				progressBarForm.Show(this.m_hWndRevit);
				List<FamilyInstance> list = new List<FamilyInstance>();
				foreach (CableTray cableTray in lstCableTary)
				{
					foreach (Autodesk.Revit.DB.Document doc in this.m_lstDoc)
					{
						list.AddRange(Interface.GetAllIntersectSubject<FamilyInstance>(cableTray, doc, BuiltInCategory.OST_StructuralFraming));
					}
					if (list.Count == 0)
					{
						progressBarForm.RefreshProgressBar();
					}
					else
					{
						if (!this.TraveAllBeam(list, cableTray, lstInfos, ref lstDbOpening))
						{
							progressBarForm.Dispose();
							return false;
						}
						list.Clear();
						progressBarForm.RefreshProgressBar();
						if (progressBarForm.m_stopTag)
						{
							return false;
						}
					}
				}
				progressBarForm.Dispose();
			}
			catch (Exception ex)
			{
				progressBarForm.Dispose();
				ExceptionLog.WriteLog(ex.Message, true);
				return false;
			}
			return true;
		}

		private bool GetOpeningDataByPipe(List<Pipe> lstPipe, List<HYOpeningDesignInput.Public.PointSort> lstInfos, ref LinkedList<DbOpeningBase> lstDbOpening)
		{
			ProgressBarForm progressBarForm = new ProgressBarForm(lstPipe.Count, ProgressBarStyle.Blocks, true);
			try
			{
				progressBarForm.Text = "水管和梁碰撞检测";
				progressBarForm.ShowInTaskbar = false;
				progressBarForm.Show(this.m_hWndRevit);
				List<FamilyInstance> list = new List<FamilyInstance>();
				foreach (Pipe pipe in lstPipe)
				{
					foreach (Autodesk.Revit.DB.Document doc in this.m_lstDoc)
					{
						list.AddRange(Interface.GetAllIntersectSubject<FamilyInstance>(pipe, doc, BuiltInCategory.OST_StructuralFraming));
					}
					if (list.Count == 0)
					{
						progressBarForm.RefreshProgressBar();
					}
					else
					{
						if (!this.TraveAllBeam(list, pipe, lstInfos, ref lstDbOpening))
						{
							progressBarForm.Dispose();
							return false;
						}
						list.Clear();
						progressBarForm.RefreshProgressBar();
						if (progressBarForm.m_stopTag)
						{
							return false;
						}
					}
				}
				progressBarForm.Dispose();
			}
			catch (Exception ex)
			{
				progressBarForm.Dispose();
				ExceptionLog.WriteLog(ex.Message, true);
				return false;
			}
			return true;
		}

		private bool TraveAllBeam(List<FamilyInstance> lstBeam, Element mepCurveElem, List<HYOpeningDesignInput.Public.PointSort> lstInfos, ref LinkedList<DbOpeningBase> lstDbOpening)
		{
			try
			{
				Line mepcurveLine = Interface.GetMEPCurveLine(mepCurveElem);
				if (mepcurveLine == null)
				{
					return false;
				}
				foreach (FamilyInstance familyInstance in lstBeam)
				{
					foreach (XYZ xyz in Interface.GetCvIntersect2ElemPoints(mepcurveLine, familyInstance))
					{
						if (xyz != null)
						{
							OpeningData openingData = new OpeningData();
							DbOpeningBase value = null;
							OpeningProfileBase openingProfileBase = null;
							if (mepCurveElem is Duct)
							{
								value = new DbRectBeamOpening();
								if (!Interface.GetOpeningDatas(ref value, ref openingData, xyz, familyInstance, mepCurveElem, lstInfos))
								{
									continue;
								}
								openingProfileBase = new OpeningProfileRect();
								OpeningProfileRect openingProfileRect = openingProfileBase as OpeningProfileRect;
								openingProfileRect.m_cutHeight = openingData.m_cutHeight;
								openingProfileRect.m_cutWidth = openingData.m_cutWidth;
								openingData.m_extendDist = AssistFunc.mmToFeet(Convert.ToDouble(this.m_dicOpeningProfileData["RectOpeningOutSize"]));
							}
							else if (mepCurveElem is CableTray)
							{
								value = new DbRectBeamOpening();
								if (!Interface.GetOpeningDatas(ref value, ref openingData, xyz, familyInstance, mepCurveElem, lstInfos))
								{
									continue;
								}
								openingData.m_extendDist = AssistFunc.mmToFeet(Convert.ToDouble(this.m_dicOpeningProfileData["RectOpeningOutSize"]));
								openingProfileBase = new OpeningProfileRect();
								OpeningProfileRect openingProfileRect2 = openingProfileBase as OpeningProfileRect;
								openingProfileRect2.m_cutHeight = openingData.m_cutHeight;
								openingProfileRect2.m_cutWidth = openingData.m_cutWidth;
							}
							else if (mepCurveElem is Pipe)
							{
								value = new DbCircleBeamOpening();
								if (!Interface.GetOpeningDatas(ref value, ref openingData, xyz, familyInstance, mepCurveElem, lstInfos))
								{
									continue;
								}
								openingProfileBase = new OpeningProfileCircle();
								(openingProfileBase as OpeningProfileCircle).m_dCutDiameter = openingData.m_cutDia;
								openingData.m_extendDist = AssistFunc.mmToFeet(Convert.ToDouble(this.m_dicOpeningProfileData["CircleOpeningOutSize"]));
							}
							openingData.m_tolerance = AssistFunc.mmToFeet(Convert.ToDouble(this.m_dicOpeningProfileData["CompositeTolerance"]));
							Interface.SetOpeningProfile(ref openingProfileBase, openingData);
							Interface.SetOpeningData2Opening(openingData, ref value, openingProfileBase);
							lstDbOpening.AddLast(value);
						}
					}
				}
			}
			catch (Exception ex)
			{
				ExceptionLog.WriteLog(ex.Message, true);
				return false;
			}
			return true;
		}
	}
}
